﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using System.Xml.Xsl;
using System.IO;
using System.Xml;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Collections.Specialized;

namespace XSLTLookupField
{
    [DefaultProperty("FieldName")]
    [ToolboxData("<{0}:XSLTLookupFieldRenderingControl runat=server></{0}:XSLTLookupFieldRenderingControl>")]
    [ParseChildren(ChildrenAsProperties = true), PersistChildren(false)]
    [NonVisualControl, Bindable(false)]
    public class XSLTLookupFieldRenderingControl : BaseFieldControl
    {
        protected override void OnLoad(EventArgs e)
        {
            base.ControlMode = SPControlMode.Display;

            base.OnLoad(e);
        }

        [Bindable(true)]
        [Category("Advanced")]
        [DefaultValue("")]
        [Localizable(false)]
        public string XSLTLink
        {
            get;
            set;
        }

        private ParameterCollection _Parameters = new ParameterCollection();

        [PersistenceMode(PersistenceMode.InnerProperty), DefaultValue((string)null)]
        public ParameterCollection Parameters
        {
            get
            {
                return _Parameters;
            }
        }


        private string displayoutput = null;

        private void GetOutput()
        {
            SPSite currentsite = null;
            SPSite lisite = null;
            SPWeb liweb = null;

            try
            {
                // Create a new elevated-priviliges SPSite
                currentsite = new SPSite(SPContext.Current.Site.ID);

                string Xslt = null;

                #region Retrieve XSLT from document library by Url
                string ServerRelativeFolder = SPUrlUtility.CombineUrl(currentsite.RootWeb.RootFolder.ServerRelativeUrl, XSLTLink);
                SPFolder folder = currentsite.RootWeb.GetFolder(ServerRelativeFolder);
                Xslt = folder.ParentWeb.GetFileAsString(ServerRelativeFolder);
                #endregion

                List<SPListItem> listitems = new List<SPListItem>();

                #region GetListitems
                SPFieldLookup lookupfield = (SPFieldLookup)this.Field;
                using (SPWeb web = SPContext.Current.Site.OpenWeb(lookupfield.LookupWebId))
                {
                    SPList list = null;

                    Guid listguid = Guid.Empty;
                    try
                    {
                        // I've seen the LookupList to have a name, a guid with curly-parenthesis and without curly-parenthesis.
                        listguid = new Guid(lookupfield.LookupList);
                    }
                    catch
                    {
                        listguid = Guid.Empty;
                    }

                    if (listguid != Guid.Empty)
                    {
                        list = web.Lists[listguid];
                    }
                    else
                    {
                        list = web.Lists[lookupfield.LookupList];
                    }

                    SPFieldLookupValueCollection fieldvaluecollection = null;
                    if (ItemFieldValue is SPFieldLookupValueCollection)
                    {
                        fieldvaluecollection = (SPFieldLookupValueCollection)ItemFieldValue;
                    }
                    else
                    {
                        fieldvaluecollection = new SPFieldLookupValueCollection((string)ItemFieldValue);
                    }

                    foreach (SPFieldLookupValue value in fieldvaluecollection)
                    {
                        listitems.Add(list.GetItemById(value.LookupId));
                    }
                }
                #endregion

                #region Transform XSLT
                if (!string.IsNullOrEmpty(Xslt))
                {
                    StringWriter output = new StringWriter();

                    XsltArgumentList argumentlist = new XsltArgumentList();
                    IOrderedDictionary values = Parameters.GetValues(HttpContext.Current, this);

                    foreach (Parameter parameter in Parameters)
                    {
                        if (parameter.Direction == System.Data.ParameterDirection.InputOutput || parameter.Direction == System.Data.ParameterDirection.Input)
                        {
                            argumentlist.AddParam(parameter.Name, string.Empty, values[parameter.Name]);
                        }
                    }
                    XSLTHelper.Transform(Xslt, listitems, argumentlist, output);

                    displayoutput = output.ToString();
                }
                #endregion
            }
            catch (Exception ex)
            {
                displayoutput = ex.ToString();
            }
            finally
            {
                if (currentsite != null) currentsite.Dispose();
                if (liweb != null) liweb.Dispose();
                if (lisite != null) lisite.Dispose();
            }
        }


        protected override void RenderFieldForDisplay(HtmlTextWriter output)
        {
            if (!string.IsNullOrEmpty(XSLTLink) && Field != null && ItemFieldValue != null && SPContext.Current != null)
            {
                displayoutput = null;

                // Run the code with Elevated Privileges to ensure correct functioning
                SPSecurity.CodeToRunElevated code = new SPSecurity.CodeToRunElevated(GetOutput);
                SPSecurity.RunWithElevatedPrivileges(GetOutput);

                if (displayoutput != null) output.Write(displayoutput);
            }
            else
            {
                base.RenderFieldForDisplay(output);
            }
        }

    }
}
